#pragma once

#include <vector>
#include <queue>
#include <functional>
#include <mutex>
#include <condition_variable>
#include <thread>
#include <future>
#include <stdexcept>

namespace sl {

class ThrdPool{
  public:
    ThrdPool();
    explicit ThrdPool(size_t thread_count);

    ThrdPool(const ThrdPool&)            = delete;
    ThrdPool& operator=(const ThrdPool&) = delete;
    ThrdPool(ThrdPool&&)                 = delete;
    ThrdPool& operator=(ThrdPool&&)      = delete;

    ~ThrdPool();

    // 提交任务：返回 std::future 用于获取结果
    template <typename F, typename... Args>
    requires std::invocable<F, Args...>
    auto submit(F&& f, Args&&... args)
        -> std::future<std::invoke_result_t<F, Args...>>
    {
        using ReturnType = std::invoke_result_t<F, Args...>;
        auto task        = std::make_shared<std::packaged_task<ReturnType()>>(
            std::bind(std::forward<F>(f), std::forward<Args>(args)...));
        auto future = task->get_future();

        {
            std::unique_lock lock(mtx_);
            if(stopped_) {
                throw std::runtime_error("ThreadPool is already stopped");
            }
            tasks_.emplace([task]() { (*task)(); });
        }

        cv_.notify_one();
        return future;
    }

  private:
    std::vector<std::jthread>         workers_;
    std::queue<std::function<void()>> tasks_;

    std::mutex              mtx_;
    std::condition_variable cv_;
    bool                    stopped_ = false;

    void start_workers(size_t thread_count);
    // 工作线程
    void worker_loop(size_t index);
};

} // namespace sl